package com.haojiangbo.hander;

import com.haojiangbo.utils.MyByteBufUtils;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.fengfei.lanproxy.protocol.Constants;
import org.fengfei.lanproxy.server.config.ProxyConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

public class NginxChangeHander extends ChannelInboundHandlerAdapter {
    static Bootstrap postMain = new Bootstrap();
    static {
        NioEventLoopGroup serverWorkerGroup = new NioEventLoopGroup();
        postMain.group(serverWorkerGroup).
                channel(NioSocketChannel.class);
        postMain.handler(new ChannelInitializer<SocketChannel>(){
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new PostManHander());
            }
        });
    }

    private static Logger logger = LoggerFactory.getLogger(NginxChangeHander.class);

    @Override
    public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
        final ByteBuf byteBuf = (ByteBuf) msg;
        String http =  MyByteBufUtils.byteBuf2String(byteBuf);
        logger.info("http...{}", http);
        String[] httpList =  http.split("\r\n");
        String hostName = "";

        for(int i = 0; i < httpList.length; i++){
            if(httpList[i].contains("Host:")){
                hostName =   httpList[i].replace("Host:", "").trim();
                break;
            }
        }

        final Channel targetChange =   ctx.channel().attr(Constants.NEXT_CHANNEL).get();
        if(null != targetChange && targetChange.isActive()){
            logger.warn("targetChange status...{} isActive ... {}", targetChange,targetChange.isActive());
            targetChange.writeAndFlush(byteBuf);
            return;
        }
        final String hostNames [] = hostName.split("\\.");
        /*
        InetSocketAddress sa = (InetSocketAddress) ctx.channel().localAddress();
         */
        logger.info("主机名字1 = {}",hostName);
        if(hostNames.length < 3){
            logger.error("错误的域名信息,必须携带主机信息 当前域名 = {}", hostName);
            ctx.close();
            return;
        }
        final Integer port = ProxyConfig.hostName2protMapping.get(hostNames[0]);
        if(null == port){
            ctx.close();
            return;
        }
        logger.info("准备连接 == h = 127.0.0.1 p =  {}",port);
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1",port);
        postMain.connect(inetSocketAddress).addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()) {
                    final Channel postManChange = future.channel();
                    logger.info("客户端连接成功 == k = {} = {}",port, postManChange);
                    ctx.channel().attr(Constants.NEXT_CHANNEL).set(postManChange);
                    postManChange.attr(Constants.NEXT_CHANNEL).set(ctx.channel());
                    postManChange.writeAndFlush(byteBuf);
                }else{
                    logger.info("客户端连接失败 == k = {} = {}",port);
                    ctx.channel().close();
                }
            }
        });
        //super.channelRead(ctx, msg);
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        // cause.printStackTrace();
        /**
         * 释放change 并删除掉 map对应关系
         */
        Channel targetChange =   ctx.channel().attr(Constants.NEXT_CHANNEL).get();
        ctx.channel().attr(Constants.NEXT_CHANNEL).remove();
        if(null != targetChange){
            targetChange.attr(Constants.NEXT_CHANNEL).remove();
            targetChange.close();
        }
        ctx.close();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel targetChange =   ctx.channel().attr(Constants.NEXT_CHANNEL).get();
        if(null != targetChange){
            targetChange.attr(Constants.NEXT_CHANNEL).remove();
            targetChange.close();
        }
        ctx.channel().attr(Constants.NEXT_CHANNEL).remove();
        ctx.close();
    }
}
